package com.sinog.basic.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sinog.basic.mapper.ResourceMapper;
import com.sinog.basic.mapper.UserMapper;
import com.sinog.basic.service.ResourceService;
import com.sinog.core.domain.Resource;
import com.sinog.core.domain.RoleRes;
import com.sinog.core.model.Menu;
import com.sinog.core.util.JsonUtil;
import com.sinog.core.utilbean.Constants;
import com.sinog.core.utilbean.IdGen;
import com.sinog.core.utilbean.Result;
import com.sinog.core.utilbean.ReturnCode;
import lombok.val;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

/**
 * @desc 系统管理 - 资源管理 - 资源管理 - ResourceServiceImpl
 * @author zy
 * @date -
 */
@Service
public class ResourceServiceImpl extends ServiceImpl<ResourceMapper,Resource> implements ResourceService {

    @Autowired
    private UserMapper userMapper;

    /**
     * 系统管理 - 资源管理 - 资源管理 - 保存资源信息信息
     * @param resource resource
     * @return Result
     */
    @Override
    public Result save(String resource) {
        Resource bean = JsonUtil.toBean(resource,Resource.class);
        String size = bean.getSize();
        if(StringUtils.isNotBlank(size)) {
            String[] temp = size.split(":");
            String mark = "*";
            if(!StringUtils.equalsIgnoreCase(temp[0],mark)) {
                bean.setWidth(Integer.valueOf(temp[0]));
            }
            if(!StringUtils.equalsIgnoreCase(temp[1],mark)) {
                bean.setHeight(Integer.valueOf(temp[1]));
            }
        }
        if(null == bean.getId()) {
            bean.setId(IdGen.get().next());
        }
        boolean success = bean.insertOrUpdate();
        if(success) {
            return Result.success("保存成功");
        }
        return Result.failure(ReturnCode.SAVE_FAILED);
    }

    /**
     * 系统管理 - 资源管理 - 资源管理 - 批量删除资源信息信息
     * @param ids ids
     * @return Result
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result deleteBatch(String[] ids) {
        Resource resource = new Resource();
        boolean successResource = !resource.delete(new QueryWrapper<Resource>().in("id",ids));
        RoleRes roleRes = new RoleRes();
        boolean successRoleRes = !roleRes.delete(new QueryWrapper<RoleRes>().in("resid", ids));
        if(successResource && successRoleRes) {
            return Result.failure(ReturnCode.DELETE_FAILED);
        }
        return Result.success();
    }

    /**
     * 系统管理 - 资源管理 - 资源管理 - 根据ID查询单个资源信息
     * @param id id
     * @return Result
     */
    @Override
    public Result selectOne(String id) {
        Resource bean = new Resource();
        Resource res = bean.selectOne(new QueryWrapper<Resource>().eq("id",id));
        if(null != res) {
            String size = "";
            Integer width = res.getWidth();
            Integer height = res.getHeight();
            if(null != res.getWidth() && 0 != res.getWidth()) {
                size = width.toString();
                if(null != height && 0 != height) {
                    size += ":" + height;
                } else {
                    size += ":*";
                }
            } else if(null != height && 0 != height) {
                size = "*:" + height;
            }
            res.setSize(size);
            return Result.success(res);
        }
        return Result.failure(ReturnCode.SELECT_FAILED);
    }

    /**
     * 系统管理 - 资源管理 - 资源管理 - 加载资源管理模块的资源树
     * @param reskey reskey
     * @return Result
     */
    @Override
    public Result selectResourceAsTree(String reskey) {
        Resource bean = new Resource();
        QueryWrapper<Resource> queryWrapper = new QueryWrapper<Resource>().select("id","pid","name AS text","fn_isLeaf(id) AS isLeaf");
        String mark = Constants.NumberStr.NUM_STR_FU_ONE;
        if(!StringUtils.equalsIgnoreCase(mark,reskey)) {
            queryWrapper.like("id",reskey).or().like("name",reskey);
        }
        List<Resource> list = bean.selectList(queryWrapper.orderByAsc("type","sn","pid","id"));
        if(!list.isEmpty()) {
            return Result.success(list);
        }
        return Result.failure(ReturnCode.SELECT_FAILED);
    }

    /**
     * 系统管理 - 资源管理 - 资源管理 - 复制自己的资源到某一个资源菜单下
     * @param src src
     * @param dest dest
     * @return Result
     */
    @Override
    public Result copyResources(Long src,Long dest) throws CloneNotSupportedException {
        Resource bean = new Resource();
        QueryWrapper<Resource> queryWrapper = new QueryWrapper<Resource>().apply("FIND_IN_SET(id,fn_getChilds({0}))",src);
        List<Resource> oldResources = bean.selectList(queryWrapper);
        Map<Long,Long> map = new HashMap<>(32);
        oldResources.forEach(res -> map.put(res.getId(),IdGen.get().next()));
        boolean success = false;
        for(Resource old : oldResources) {
            val res = old.clone();
            Long pid = old.getPid();
            res.setPid(map.getOrDefault(pid,dest));
            res.setId(map.get(old.getId()));
            success = res.insert();
        }
        if(success) {
            return Result.success("保存成功");
        }
        return Result.failure(ReturnCode.SAVE_FAILED);
    }

    /**
     * 系统管理 - 资源管理 - 资源管理 - 加载首页导航栏菜单
     * @param account account
     * @return Result
     */
    @Override
    public Result selectResouceMenu(String account) {
        List<String> roles = userMapper.selectUserRoles(account);
        List<Menu> list = baseMapper.selectResouceMenu(account,roles);
        if(!list.isEmpty()) {
            List<Menu> root = new ArrayList<>(16);
            Map<String,Menu> map = new TreeMap<>();
            list.forEach(menu -> map.put(menu.getId(),menu));
            Set<Map.Entry<String,Menu>> entrySet = map.entrySet();
            entrySet.forEach(entry -> {
                Menu menu = entry.getValue();
                String pid = menu.getPid();
                String mark = Constants.NumberStr.NUM_STR_FU_ONE;
                if(StringUtils.equalsIgnoreCase(pid,mark)) {
                    root.add(menu);
                } else {
                    Menu parent = map.get(pid);
                    if(null != parent) {
                        List<Menu> children = parent.getChildren();
                        children.add(menu);
                        //子元素排序
                        Collections.sort(children);
                    }
                }
            });
            //根元素排序
            Collections.sort(root);
            return Result.success(root);
        }
        return Result.failure(ReturnCode.SELECT_FAILED);
    }
}